package cn.levi.dict.enums;

import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 枚举基类接口
 * 包含 code 和 name 属性
 */
public interface BaseEnum<T> {

    /**
     * 获取枚举代码
     */
    T getCode();

    /**
     * 获取枚举名称
     */
    String getName();

    /**
     * 根据代码获取枚举实例
     */
     static <T,E extends Enum<E> & BaseEnum<T>> E getByCode(Class<E> enumClass, T code) {
        if (code == null) {
            return null;
        }
        return CacheHolder.getCache(enumClass).get(code);
    }

    /**
     * 根据代码获取枚举名称
     */
     static <T,E extends Enum<E> & BaseEnum<T>> String getNameByCode(Class<E> enumClass, T code) {
        E enumInstance = getByCode(enumClass, code);
        return enumInstance != null ? enumInstance.getName() : null;
    }
    /**
     * 根据名称获取枚举code
     */
    static <T,E extends Enum<E> & BaseEnum<T>> T getCodeByName(Class<E> enumClass, String name) {
        if (name == null) {
            return null;
        }
        return Arrays.stream(enumClass.getEnumConstants())
                .filter(e -> name.equals(e.getName()))
                .findFirst()
                .map(BaseEnum::getCode)
                .orElse(null);
    }


    /**
     * 检查代码是否存在
     */
     static <T,E extends Enum<E> & BaseEnum<T>> boolean containsCode(Class<E> enumClass, T code) {
        return getByCode(enumClass, code) != null;
    }


    /**
     * 获取所有枚举的映射表 (code -> name)
     */
     static <T,E extends Enum<E> & BaseEnum<T>> Map<T, String> getEnumMap(Class<E> enumClass) {
        return Arrays.stream(enumClass.getEnumConstants())
                .collect(Collectors.toMap(BaseEnum::getCode, BaseEnum::getName));
    }

    /**
     * 缓存持有类
     */
     class CacheHolder {
        private static final Map<Class<?>, Map<?, ?>> CACHE_MAP = new ConcurrentHashMap<>();

        /**
         * 获取枚举的缓存映射表
         */
        @SuppressWarnings("unchecked")
        public static <T,E extends Enum<E> & BaseEnum<T>> Map<T, E> getCache(Class<E> enumClass) {
            return (Map<T, E>) CACHE_MAP.computeIfAbsent(enumClass, clazz ->
                Arrays.stream(enumClass.getEnumConstants())
                      .collect(Collectors.toMap(BaseEnum::getCode, e -> e))
            );
        }
    }
}
